#ifndef oct_toolkits_h
#define oct_toolkits_h
#include <string>


namespace oct_toolkits
{


	/// 定义导出符
	/// ---------------------------------------------------------------------------------------
#if defined(_WIN32) || defined(_WIN64) || defined(WIN32)
	/// ---------------------------------------------------------------------------------------------
	#ifndef lib_toolkits_api
		#define lib_toolkits_api	__declspec(dllexport)
	#else
		#define lib_toolkits_api	__declspec(dllimport)
	#endif /// !lib_toolkits_api

#elif defined(_unix_) || defined(_linux_) || defined(_unix) || defined(_linux) || defined(__unix)
	/// ---------------------------------------------------------------------------------------------
	#ifndef lib_toolkits_api
		#define lib_toolkits_api	__attribute__((visibility ("default")))
	#endif /// !lib_toolkits_api

#endif /// !defined(_WIN32) || defined(_WIN64) || defined(WIN32)






	
	/// ----------------------------------------------------------------------------------------
	/// 文件操作
	enum en_file_open_mode
	{
		/// 以只读方式打开文件，只允许读取，不允许写入。该文件必须存在。
		kmode_r				= 0,
		/// 	以读/写方式打开文件，允许读取和写入。该文件必须存在。
		kmode_rp			= 1,
		/// 以读/写方式打开一个二进制文件，允许读/写数据。
		kmode_rbp			= 2,
		/// 	以读/写方式打开一个文本文件，允许读和写。
		kmode_rtp			= 3,
		/// 以只写方式打开文件，若文件存在则长度清为0，即该文件内容消失，若不存在则创建该文件。
		kmode_w				= 5,
		/// 	以读/写方式打开文件，若文件存在则文件长度清为零，即该文件内容会消失。若文件不存在则建立该文件。
		kmode_wp			= 6,
		/// 以追加的方式打开只写文件。若文件不存在，则会建立该文件，如果文件存在，写入的数据会被加到文件尾，即文件原先的内容会被保留（EOF符保留)。
		kmode_append		= 7,
		/// 以追加方式打开可读/写的文件。若文件不存在，则会建立该文件，如果文件存在，则写入的数据会被加到文件尾后，即文件原先的内容会被保留（原来的EOF符 不保留)。
		kmode_append_p		= 8,
		/// 	以只写方式打开或新建一个二进制文件，只允许写数据。
		kmode_wb			= 9,
		/// 以读/写方式打开或建立一个二进制文件，允许读和写。
		kmode_wbp			= 10,
		/// 以读/写方式打开或建立一个文本文件，允许读写
		kmode_wtp			= 11,
		/// 以读/写方式打开一个文本文件，允许读或在文本末追加数据。
		kmode_atp			= 12,
		/// 以读 / 写方式打开一个二进制文件，允许读或在文件末追加数据。
		kmode_abp			= 13,

	};

	/// ----------------------------------------------------------------------------------------
		/// 年月日时分秒毫秒
	struct st_now_date_
	{
		unsigned short	year_;
		unsigned char	month_;
		unsigned char	day_;

		unsigned char	hour_;
		unsigned char	minute_;
		unsigned char	second_;
		unsigned short	mill_sec_;		/// 毫秒

		void zero_()
		{
			memset(this, 0, sizeof(st_now_date_));
		}

		st_now_date_()
		{
			zero_();
		}
	};
	typedef st_now_date_ st_now_date;

	/// ----------------------------------------------------------------------------------------
	enum
	{
		/// 日志文件大小: 5M
		klog_file_size		= 5 * 1024 * 1024,
	};

	struct st_log_info_
	{
		/// 日志文件存在路径, 例如: c:/logs/demo, 也支持： c:\\logs\\demo
		std::string			path_;
		/// 日志文件名前缀	例如： C_2021_03_27中，前缀就是 C
		std::string			prefix_;
		/// 日志文件名后缀	例如： 2021_03_27_C 中， 后缀就是 C
		std::string			postfix_;
		/// 日志文件格式	例如： C_2021_03_27.log中， ".log"就是文件格式 )
		std::string			type_;
		/// 日志文件大小	,	默认大小为 5M 
		unsigned int		size_;

		void zero_()
		{
			path_.clear();
			prefix_.clear();
			postfix_.clear();
			type_.clear();
			size_			= klog_file_size;
		}


		st_log_info_()
		{
			zero_();
		}
	};

	typedef st_log_info_	st_log_info;



	/// ----------------------------------------------------------------------------------------
	/// 文件读写接口
	/// ----------------------------------------------------------------------------------------
	class ifile
	{
	public:

		///  --------------------------------------------------------------------------------
		///  @brief:	初始化
		///  @str_file - 文件所在绝对路径， 例如： C:/demo/logs/1.txt
		///  @open_mode - 以哪种方式打开文件
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败, 参数【str_file】字符串为空
		///				2 - 失败，参数【open_mode】不是给定的枚举范围
		///				3 - 失败，文件打开失败。
		///  --------------------------------------------------------------------------------
		virtual int init_(const std::string& str_file, const oct_toolkits::en_file_open_mode open_mode) = 0;


		///  --------------------------------------------------------------------------------
		///  	返回当前初始化的文件
		///  @return - std::string	
		/// 			
		///  --------------------------------------------------------------------------------
		virtual std::string file_() = 0;


		///  --------------------------------------------------------------------------------
		///  	文件是否打开
		///  @return - bool	
		/// 			true - 打开
		///				false - 没有打开
		///  --------------------------------------------------------------------------------
		virtual bool is_opened_() = 0;


		///  --------------------------------------------------------------------------------
		///  	返回文件长度,单位： 字节
		///  @return - int	
		/// 			返回值X， 
		///				-2 - 失败，请先执行初始化
		///				X >=0 , 文件长度，单位：字节
		///  --------------------------------------------------------------------------------
		virtual int length_() = 0;


		///  --------------------------------------------------------------------------------
		///  	写文件, 将数据写入
		///  @pbuf - 待写入内容
		///  @pbuf_len - 待写入数据长度
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败，请先初始化
		///				2 - 失败，参数【pbuf】为nullptr或者NULL
		///				3 - 失败，写文件失败
		///  --------------------------------------------------------------------------------
		virtual int write_(const char* pbuf, unsigned int pbuf_len) = 0;
		///  --------------------------------------------------------------------------------
		///  	写文件
		///  @str_write - 待文件内容
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败，请先初始化
		///				2 - 失败，参数【str_write】的长度为0
		///				3 - 失败，写文件失败
		///  --------------------------------------------------------------------------------
		virtual int write_(const std::string& str_write) = 0;

		///  --------------------------------------------------------------------------------
		///  	将文件内容儒道参数【str_read】中
		///  @str_read - 返回文件内容
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败，请先初始化
		///				2 - 失败，读取文件缓冲创建失败
		///				3 - 失败，读取文件失败
		///  --------------------------------------------------------------------------------
		virtual int read_(std::string& str_read) = 0;

		///  --------------------------------------------------------------------------------
		///   读文件内容， 参数【pout_buf】需要外部申请，函数内不会维护，读取成功后，文件内容存放在pout_buf中。
		///  @pout_buf - 返回读取文件内容
		///  @pout_buf_len - 【pout_buf】缓冲区的长度
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败，请先初始化
		///				2 - 失败，参数【pout_buf】为空 或者 参数【pout_buf_len】的值是0
		///  --------------------------------------------------------------------------------
		virtual int read_(char* pout_buf, unsigned int pout_buf_len) = 0;

		///  --------------------------------------------------------------------------------
		///  	判断参数【str_check_file】的文件是否存在
		///  @str_check_file - 
		///  @return - bool	
		/// 			
		///  --------------------------------------------------------------------------------
		virtual bool is_existed_(const std::string& str_check_file) = 0;

		///  --------------------------------------------------------------------------------
		///  	避免析构时出现异常，请销毁前先调用该函数完成内部资源释放
		///  @return - int	
		/// 			0 - 成功
		///  --------------------------------------------------------------------------------
		virtual int uninit_() = 0;
	};



	/// ----------------------------------------------------------------------------------------
	/// 导出函数
#ifdef __cplusplus
	extern "C" {
#endif/// 

		///  --------------------------------------------------------------------------------
		///  	创建文件读写对象
		///  @return - lib_toolkits_api ifile*	
		/// 			返回模块对象，如果创建失败，则返回NULL
		///  --------------------------------------------------------------------------------
		lib_toolkits_api ifile* create_ifile_();

		///  --------------------------------------------------------------------------------
		///  	释放文件模块, 释放后，函数内部将其置为NULL，
		///  @pobj - 来自函数【create_ifile_】创建的结果
		///  @return - lib_toolkits_api ifile*	
		/// 		
		///  --------------------------------------------------------------------------------
		lib_toolkits_api ifile* release_ifile_(ifile* pobj);


#ifdef __cplusplus
	}
#endif/// 





	/// ----------------------------------------------------------------------------------------
	/// 日志文件接口类
	/// ----------------------------------------------------------------------------------------
	class ilog
	{
	public:
		///  --------------------------------------------------------------------------------
		///  	初始化， 
		///  @info - 日志信息
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败，日志文件路径不正确
		///				2 - 失败，如果磁盘空间剩余不够，则禁止创建日志文件对象
		///				3 - 失败，无法创建日志文件路径， 无法写入日志
		///				5 - 失败，创建日志文件失败，则无法写入日志
		///  --------------------------------------------------------------------------------
		virtual int init_(const oct_toolkits::st_log_info& info) = 0;




		///  --------------------------------------------------------------------------------
		///  写日志，日志内容为文本，且每一行前面都带有时间； 例如： [2021-03-28 15:00:00:001] 日志文件内容
		///  @str_log - 待写入日志文件内容
		///  @return - int	
		/// 			0 - 成功
		///				1 - 无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
		///				2 - 失败，无法创建写日志文件对象，请先初始化
		///  --------------------------------------------------------------------------------
		virtual int log_text_(const std::string& str_log) = 0;

		///  --------------------------------------------------------------------------------
		///  	写日志
		///  @pdata - 待写入内容
		///  @pdata_len - 待写入长度
		///  @return - int	
		/// 			0 - 成功、
		///				1 - 失败，参数【pdata】为空或者参数【pdata_len】为0
		///				2 - 失败，无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
		///				3 - 失败，无法写入，日志文件读写对象创建失败，请先初始化
		///  --------------------------------------------------------------------------------
		virtual int log_text_(const char* pdata, unsigned int pdata_len) = 0;

		///  --------------------------------------------------------------------------------
		///  	将参数【str_log】每个字节的16进制写入文件，全部大写
		///  @str_log - 待写入内容
		///  @return - int	
		///				0 - 成功
		/// 			1 - 无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
		///				2 - 失败，无法写入，日志文件读写对象创建失败，请先初始化
		///  --------------------------------------------------------------------------------
		virtual int log_hex_(const std::string& str_log) = 0;

		///  --------------------------------------------------------------------------------
		///  	将参数【pdata】每个字节的16进制写入文件，全部大写
		///  @pdata - 待写入内容
		///  @pdata_len - 写入内容长度
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败，参数【pdata】为空或者参数【pdata_len】为0
		///				2 - 失败，无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
		///				3 - 失败，无法写入，日志文件读写对象创建失败，请先初始化
		///  --------------------------------------------------------------------------------
		virtual int log_hex_(const char* pdata, unsigned int pdata_len) = 0;


		///  --------------------------------------------------------------------------------
		///  	释放内部资源
		///  @return - void	
		/// 			
		///  --------------------------------------------------------------------------------
		virtual void uninit_() = 0;
	};



	/// ----------------------------------------------------------------------------------------
/// 导出函数
#ifdef __cplusplus
	extern "C" {
#endif/// 

		///  --------------------------------------------------------------------------------
		///  	创建日志文件读写对象
		///  @return - lib_toolkits_api ilog*	
		/// 			返回模块对象，如果创建失败，则返回NULL
		///  --------------------------------------------------------------------------------
		lib_toolkits_api ilog* create_ilog_();

		///  --------------------------------------------------------------------------------
		///  	释放文件模块, 释放后，函数内部将其置为NULL，
		///  @pobj - 来自函数【create_ilog_】创建的结果
		///  @return - lib_toolkits_api ilog*	
		/// 		
		///  --------------------------------------------------------------------------------
		lib_toolkits_api ilog* release_ilog_(ilog* pobj);


#ifdef __cplusplus
	}
#endif/// 





	/// ----------------------------------------------------------------------------------------
	/// 常用工具
	/// ----------------------------------------------------------------------------------------
	class lib_toolkits_api toolkits
	{
	public:
		explicit toolkits();
		virtual ~toolkits();

		///  --------------------------------------------------------------------------------
		///  	返回年月日时分秒毫秒字符串
		///  @return - std::string	
		/// 			
		///  --------------------------------------------------------------------------------
		st_now_date get_date_now_();

		///  --------------------------------------------------------------------------------
		///  	格式化字符串
		///  @pformat - 格式化字符串
		///  @ - 参数列表
		///  @return - std::string	
		/// 			返回格式化结果
		///  --------------------------------------------------------------------------------
		std::string str_format_(const char*pformat, ...);


		///  --------------------------------------------------------------------------------
		///  	获取可执行程序所在绝对路径
		///  @return - std::string	
		/// 			
		///  --------------------------------------------------------------------------------
		std::string get_executable_dir_();

	private:
		/// 屏蔽拷贝构造函数
		toolkits(const toolkits& instance) {}
		toolkits& operator =(const toolkits& instance) { return *this; }
	};

}

#endif /// oct_toolkits_h